from SimpleXMLRPCServer import SimpleXMLRPCServer
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
from Tkinter import *
import random
import pickle
from batiment import *
from Etoile import *
from Planete import *
from unite import *
from univers import *
from Joueur import *
from modeleClient import *
import Intelligence
import threading

class Serveur(object):
    def __init__(self):
        self.modele=Modele(self)
        self.partieEnCours=0
        self.listeJoueurs={}
        self.bin={}
        self.ai={}
        self.poolCouleurs = ["orange","green","royal blue","sea green","violet red","maroon"]
        #threading.Timer(0.1,self.loopControle).start()
        self.compteur = 0

    ##le modele envoie au serveur l'univers nouvellement cree
    def creerUnivers(self, univers, nbAI):
        self.modele.univers=pickle.loads(univers)
        self.creerAI(pickle.loads(nbAI))
        self.partieEnCours=1
        threading.Timer(0.1,self.loopControle).start()
        return "ok"
    
    def creerAI(self, nbAI):
        for AI in range(1,nbAI+1):
            nom = "ai"+str(AI)
            etoileDepart=0
            ##trouver une etoile libre
            while self.modele.univers.tabEtoiles[etoileDepart].proprietaire<>"":
                etoileDepart+=1
            ##amenager l'etoile
            self.modele.univers.tabEtoiles[etoileDepart].proprietaire = nom
            stationSpatiale=Structure('stationSpatiale',self.modele.univers.tabEtoiles[etoileDepart])
            self.modele.univers.tabEtoiles[etoileDepart].tabStructures.append(stationSpatiale)
            
            self.modele.univers.tabEtoiles[etoileDepart].tabPlanetes=[]
            self.modele.univers.tabEtoiles[etoileDepart].tabPlanetes.append(Planete(2500, 0, 0, "Morte", self.modele.univers.tabEtoiles[etoileDepart]))
            self.modele.univers.tabEtoiles[etoileDepart].tabPlanetes.append(Planete(0, 0, 2500, "Gazeuse", self.modele.univers.tabEtoiles[etoileDepart]))
            self.modele.univers.tabEtoiles[etoileDepart].tabPlanetes.append(Planete(1000, 300, 1000, "Habitable", self.modele.univers.tabEtoiles[etoileDepart]))
            self.modele.univers.tabEtoiles[etoileDepart].mineraiMax=3500
            self.modele.univers.tabEtoiles[etoileDepart].populationMax=300
            self.modele.univers.tabEtoiles[etoileDepart].gazMax=3500
            self.modele.univers.tabEtoiles[etoileDepart].population=100
            self.modele.univers.tabEtoiles[etoileDepart].nourriture=100
            ##creer le scout de depart
            indexUnite=len(self.modele.univers.tabUnites)
            uniteDepart=Unite('scout', self.modele.univers.tabEtoiles[etoileDepart])
            self.modele.univers.tabUnites.append(uniteDepart)
            nb = random.randrange(len(self.poolCouleurs))
            couleur = self.poolCouleurs[nb]
            self.ai[nom] = Intelligence.Intelligence(nom, etoileDepart, indexUnite, couleur)
            self.poolCouleurs.remove(couleur)
            self.listeJoueurs[nom]=self.ai[nom]

    ##confirme si oui ou non une partie est en cours
    def demanderSiPartie(self):
        if self.partieEnCours==1:
            return "oui"
        else:
            return "non"

    ##cree le nouveau joueur, amenage une etoile et retourne l'univers
    def joindrePartie(self,nick):
        etoileDepart=0
        ##trouver une etoile libre
        while self.modele.univers.tabEtoiles[etoileDepart].proprietaire<>"":
            etoileDepart+=1
        ##amenager l'etoile
        self.modele.univers.tabEtoiles[etoileDepart].proprietaire = nick
        stationSpatiale=Structure('stationSpatiale',self.modele.univers.tabEtoiles[etoileDepart])
        self.modele.univers.tabEtoiles[etoileDepart].tabStructures.append(stationSpatiale)
        
        ##forcer des valeurs par defaut dans la planete de depart
        
        self.modele.univers.tabEtoiles[etoileDepart].tabPlanetes=[]
        self.modele.univers.tabEtoiles[etoileDepart].tabPlanetes.append(Planete(2500, 0, 0, "Morte", self.modele.univers.tabEtoiles[etoileDepart]))
        self.modele.univers.tabEtoiles[etoileDepart].tabPlanetes.append(Planete(0, 0, 2500, "Gazeuse", self.modele.univers.tabEtoiles[etoileDepart]))
        self.modele.univers.tabEtoiles[etoileDepart].tabPlanetes.append(Planete(1000, 300, 1000, "Habitable", self.modele.univers.tabEtoiles[etoileDepart]))
        self.modele.univers.tabEtoiles[etoileDepart].mineraiMax=3500
        self.modele.univers.tabEtoiles[etoileDepart].populationMax=300
        self.modele.univers.tabEtoiles[etoileDepart].gazMax=3500
        self.modele.univers.tabEtoiles[etoileDepart].population=100
        self.modele.univers.tabEtoiles[etoileDepart].nourriture=100
        
        ##creer le scout de depart
        indexUnite=len(self.modele.univers.tabUnites)
        uniteDepart=Unite('scout', self.modele.univers.tabEtoiles[etoileDepart])
        self.modele.univers.tabUnites.append(uniteDepart)
        ##creer le joueur
        nb = random.randrange(len(self.poolCouleurs))
        couleur = self.poolCouleurs[nb]
        self.listeJoueurs[nick]=Joueur(nick, etoileDepart, indexUnite, couleur)
        self.poolCouleurs.remove(couleur)
        ##creer la bin du joueur
        self.bin[nick]=[]
        
        self.modele.univers.listeJoueurs.append(nick)
        for i in self.bin:
            if i <> nick:
                self.bin[i].append(["nouveauJoueur",nick,self.modele.univers.tabEtoiles[etoileDepart],uniteDepart, couleur])
                self.changerTextChat("vient de se connecter", nick)

        return pickle.dumps(self.modele.univers)

    ##retourne le joueur nouvellement cree
    def getJoueur(self, nick):
        return pickle.dumps(self.listeJoueurs)


    ##ajoute a toutes les bins le nouveau mouvement
    def initMouvement(self,indexUnite,x,y,z):
        self.modele.initMouvement(indexUnite,x,y,z)
        # i correspond au nom du joueur
        for i in self.bin:
            if i <> self.modele.univers.tabUnites[indexUnite].proprietaire:
                self.bin[i].append(["mvt",indexUnite,x,y,z])
        return "ok"
    
    def initAttaque(self,indexUniteAttaque,indexUniteDefense):
        self.modele.initAttaque(indexUniteAttaque,indexUniteDefense)
        # i correspond au nom du joueur
        for i in self.bin:
            if i <> self.modele.univers.tabUnites[indexUniteAttaque].proprietaire:
                self.bin[i].append(["attaque",indexUniteAttaque,indexUniteDefense])
        return "ok"
    
    def shieldDisrupt(self, indexUniteAttaque, indexUniteDefense):
        self.modele.shieldDisrupt(indexUniteDefense)
        for i in self.bin:
            if i <> self.modele.univers.tabUnites[indexUniteAttaque].proprietaire:
                self.bin[i].append(["shieldDisrupt", indexUniteDefense])
        return "ok"
    
    def initReparer(self, indexUniteReparateur, indexUniteReparer):
        self.modele.initReparer(indexUniteReparateur, indexUniteReparer)
        for i in self.bin:
            if i <> self.modele.univers.tabUnites[indexUniteReparer].proprietaire:
                self.bin[i].append(["reparer", indexUniteReparer])
        return "ok"
    
    def changerTextChat(self, nouveauChat, joueur):
        for i in self.bin:
            if i <> joueur:
                self.bin[i].append(["chat", nouveauChat, joueur])
        return "ok"
    
    def cancelAttaque(self,index):
        self.modele.cancelAttaque(index)
        # i correspond au nom du joueur
        for i in self.bin:
            if i <> self.modele.univers.tabUnites[index].proprietaire:
                self.bin[i].append(["cancelAttaque",index])
        return "ok"
    
    def creerUnite(self, indexEtoile, typeUnite):
        self.modele.creerUnite(indexEtoile, typeUnite)
        # i correspond au nom du joueur
        for i in self.bin:
            if i <> self.modele.univers.tabEtoiles[indexEtoile].proprietaire:
                self.bin[i].append(["creerUnite",indexEtoile, typeUnite])
        return "ok"
    
    def construireStructure(self,etoile,structure):
        self.modele.construireStructure(structure,etoile)
        for i in self.bin:
            if i <> self.modele.univers.tabEtoiles[etoile].proprietaire:
                self.bin[i].append(["construireStructure",structure,etoile])

        return "ok"
    
    def approprierEtoile(self, nick, index):
        index = int(index)
        self.modele.approprierEtoile(nick, index)
        for i in self.bin:
            if i <> nick:
                self.bin[i].append["appropriationEtoile", nick, index]
        return "ok"

    ##retourner la liste des changements
    def ping(self,nom):
        binTemp=self.bin[nom]
        self.bin[nom]=[]
        if binTemp == []:
            return "rien"
        else:
            return pickle.dumps(binTemp)

    def loopControle(self):
        
        if self.compteur < 7:
            self.compteur+=1
        else:
            self.gererAI()
            self.modele.changerPopulation()
            self.modele.ticBatiments()
            self.compteur=1
            self.modele.attaquer() ##attaque au 5 tics
            self.modele.reparer()
        self.modele.bougerUnites()
        self.modele.riposte()
        for i in self.modele.univers.tabUnites:
            i.hpPrePing=i.hp
            i.shieldsPrePing=i.shields
        threading.Timer(0.1, self.loopControle).start()
        
    def gererAI(self):
        for ai in self.ai:
            bin = self.ai[ai].tic(self.modele.univers)
            if bin <> []:
                for evenement in bin:
                    if evenement[0] == "mvt":
                        indexUnite = evenement[1]
                        x = evenement[2]
                        y = evenement[3]
                        z = evenement[4]
                        self.initMouvement(indexUnite, x, y, z)
                    elif evenement[0] == "creerUnite":
                        etoile = evenement[1]
                        type = evenement[2]
                        self.creerUnite(etoile, type)
                    elif evenement[0] == "attaque":
                        attaquant = evenement[1]
                        defenseur = evenement[2]
                        self.initAttaque(attaquant, defenseur)
                        


server = SimpleXMLRPCServer(("localhost", 11502),
                    requestHandler=SimpleXMLRPCRequestHandler)
server.register_introspection_functions()
server.register_instance(Serveur())
print "serveur initialise"

server.serve_forever()